import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.CharsetUtil;

import java.util.concurrent.atomic.AtomicInteger;

public class MultiAcceptorServer {
    public static void main(String[] args) throws Exception {
        // BossGroup：用于监听连接（accept）
        EventLoopGroup bossGroup = new NioEventLoopGroup(4); // 4 个线程
        // WorkerGroup：处理客户端 I/O 读写
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            final AtomicInteger connectionCount = new AtomicInteger(0);

            /**
             *  Windows 不支持多个 socket 同时监听同一个端口
             *  抛出 BindException
             *  NioServerSocketChannel[0] 已绑定到端口 8080，EventLoop: io.netty.channel.nio.NioEventLoop@2173f6d9
             */
            for (int i = 0; i < 4; i++) {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(bossGroup, workerGroup)
                         .channel(NioServerSocketChannel.class)
                         .option(ChannelOption.SO_REUSEADDR, true) // 支持多 Channel 绑定同一端口
                         .childHandler(new ChannelInitializer<SocketChannel>() {
                             @Override
                             protected void initChannel(SocketChannel ch) throws Exception {
                                 ch.pipeline()
                                   .addLast(new LoggingHandler()) // 日志记录
                                   .addLast(new SimpleChannelInboundHandler<ByteBuf>() {
                                       @Override
                                       protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
                                           System.out.println("收到消息: " + msg.toString(CharsetUtil.UTF_8));
                                           ctx.writeAndFlush(Unpooled.copiedBuffer("Hello from server", CharsetUtil.UTF_8));
                                       }

                                       @Override
                                       public void channelActive(ChannelHandlerContext ctx) {
                                           int count = connectionCount.incrementAndGet();
                                           System.out.println("客户端连接 [" + count + "] - " + ctx.channel());
                                       }

                                       @Override
                                       public void channelInactive(ChannelHandlerContext ctx) {
                                           int count = connectionCount.decrementAndGet();
                                           System.out.println("客户端断开 [" + count + "] - " + ctx.channel());
                                       }
                                   });
                             }
                         });

                // 绑定到同一个端口
                ChannelFuture future = bootstrap.bind(8080).sync();
                Channel channel = future.channel();
                System.out.println("NioServerSocketChannel[" + i + "] 已绑定到端口 8080，EventLoop: " + channel.eventLoop());
            }

            System.out.println("服务已启动，监听端口 8080，4 个 acceptor 同时监听");
            // 阻塞主线程，直到服务关闭
            Thread.sleep(Long.MAX_VALUE);

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}